#include <GL/gl.h>
#include <GL/glu.h>
#include <SDL/SDL.h>
#include <iostream>
#include "Game.h"
#include "InvisibleCube.h"
using namespace std;

Game::Game()
{
	cout << "loading textures...\n";
	textureLoader.loadTextures();
	
	cout << "loading sound...\n";
	sound = new Sound();
	
	
	cout << "creating grid size:" << GRID_SIZE << "...\n";
	cubePiles = new CubePileGrid();
	for(int i=0; i<GRID_SIZE; i++)
	{
		for(int j=0; j<GRID_SIZE; j++)
		{
			Cube * bottomCube = new Cube(&textureLoader, STONE);
			float xPos = i * (CUBE_SPACING + CUBE_GAP);
			float zPos = j * (CUBE_SPACING + CUBE_GAP);
			float yPos = 0;
			bottomCube->yPos = yPos;
			CubePile * cubePile = new CubePile(bottomCube, sound, xPos, zPos, this);
			cubePiles->set(i, j, cubePile);
		}
	}
	
	cout << "creating emitters...\n";
	cubeEmitter = new CubeEmitter(cubePiles, &textureLoader, CUBES_TO_EMIT);
	houseEmitter = new HouseEmitter(&textureLoader, cubePiles);
	
	cout << "initialising particle systems...\n";
	waterParticleSystem = new WaterParticleSystem(cubePiles, MAX_DROPS_OF_WATER);
	
	pattern = new Pattern();
	
	character = new Character(textureLoader.charTextures[0], textureLoader.speachTexture, pattern, cubePiles);
	character->moveTo(0,3);
	
	camera = new Camera();
	input.addKeyListener(camera);
	
	cursor = new Cursor(cubePiles);
	input.addKeyListener(cursor);
	input.addMouseListener(cursor);
	
	userInterface = new UserInterface(sound, cursor, new InvisibleCube());
	input.addKeyListener(userInterface);
	input.addMouseListener(userInterface);
}

Game::~Game()
{
	//TODO: delete cubes
	//TODO: delete emitter
	//TODO: delete camera
	//TODO: delete cursor
}



void Game::render()
{
	
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
	
	glPushMatrix();
	
	glTranslatef(camera->xPos, camera->yPos, camera->zPos);
	
	//cout << camera->xPos << " " << camera->yPos << " " << camera->zPos << "\n";
	
	glRotatef(camera->pitch, 1, 0, 0);

	glBlendFunc(GL_SRC_ALPHA, GL_ONE);		// Blending Function For Translucency Based On Source Alpha Value ( NEW )

	glDisable(GL_BLEND);
	for(int x=0; x<GRID_SIZE; x++)
	{
		for(int z=0; z<GRID_SIZE; z++)
		{
			cubePiles->at(x,z)->render();
		}
	}
	
	
//	glEnable(GL_DEPTH_TEST);	// Turn Depth Testing On
//	glDisable(GL_DEPTH_TEST);	// Turn Depth Testing Off
	cursor->render();

	waterParticleSystem->render();

	glPopMatrix();
	
	userInterface->render();
	
	SDL_GL_SwapBuffers();		
	
}

void Game::animate(float timeD)
{
	for(int x=0; x<GRID_SIZE; x++)
	{
		for(int z=0; z<GRID_SIZE; z++)
		{
			cubePiles->at(x,z)->animate(timeD);
		}
	}

	camera->animate(timeD);
	userInterface->animate(timeD);
	waterParticleSystem->animate(timeD);
}

void Game::main_loop_function()
{
	try
	{
		int lastTime = SDL_GetTicks();
		while (input.events())
		{
			int timeNow = SDL_GetTicks();
			float timeD = timeNow - lastTime;
			
			lastTime = timeNow;
			//std::cout << "yPos:" << cubes.at(0)->yPos << " yPos:" << cubes.at(1)->yPos << "\n";

			cubeEmitter->emit(timeD);
			if(cubeEmitter->isFinishedEmitting() && !houseEmitter->isFinishedEmitting())
			{
				houseEmitter->emit(timeD);
			}

			animate(timeD);

			render();
		}
	}
	catch(char const* error)
	{
		cout << error;
	}		
}

void Game::run()
{
	main_loop_function();
}

void Game::cubeBounceFinished(int xIndex, int zIndex)
{
	if(cubeEmitter->isFinishedEmitting() && pattern != NULL)
	{
		if(pattern->checkPattern(cubePiles, houseEmitter, &textureLoader, xIndex, zIndex))
		{
			character->patternCompleted(pattern);
			pattern = NULL;
		}
	}
}
